<template>
    <a-select
        v-bind="bindValues"
        v-model:value="selectedValue"
        show-search
        placeholder="请输入"
        label-in-value
        :default-active-first-option="false"
        :show-arrow="false"
        :filter-option="false"
        :not-found-content="null"
        @search="selectSearch"
        @change="selectChange"
        @inputKeyDown="inputKeyDown"
    >
        <template v-if="showOptions">
            <a-select-option
                v-for="item of options"
                :key="keyField ? item[keyField] : label ? item[label] : item"
                :value="keyField ? item[keyField] : label ? item[label] : item"
                v-bind="buildOptionAttrs(item)"
            >
                <slot name="label" :record="item" v-if="slotNames.includes('label')" />
                <span v-else> {{ label ? item[label] : item }} </span>
            </a-select-option>
        </template>
        <!-- 后缀图标 -->
        <template #suffixIcon><SearchOutlined class="ant-select-suffix" /></template>
    </a-select>
</template>

<script lang="ts">
import api from '@/api';
import store from '@/store';
import { message } from 'ant-design-vue';
import { SearchOutlined } from '@ant-design/icons-vue';
import { debounce } from '@/utils/util';
import { defineComponent, ref, unref, computed, watch, reactive, toRefs } from 'vue';
export default defineComponent({
    components: {
        SearchOutlined
    },
    props: {
        type: {
            type: String,
            default: ''
        }, // 类型，用来区分请求那一类的查询
        label: {
            type: String,
            default: ''
        }, //显示的字段
        keyField: {
            type: String,
            default: ''
        }, // 值字段
        searchQuery: {
            type: Object,
            default: () => ({})
        }, //额外的查询参数
        valueLabelField: {
            type: String,
            default: ''
        },
        isAllowInput: {
            type: Boolean,
            default: false
        }
    },
    emits: ['success', 'update:value', 'error', 'optionsCreated'],
    setup(props, { attrs, emit, slots }) {
        const options = ref<any[]>([]);
        const showOptions = ref(true);
        const state = reactive<any>({
            selectedValue: {
                label: '',
                value: ''
            }
        });
        const bindValues = computed(() => {
            const target = attrs['default-value'];
            if (target) {
                if (typeof target === 'string') {
                    state.selectedValue = {
                        label: target,
                        value: target
                    };
                    // 需要回显label，因为一开始默认值可以只是一个id或者code，需要从选项中找出要显示的label
                    if (target && options.value.length) {
                        const obj = options.value.find((item) => item[props.keyField] === target);
                        if (obj) {
                            state.selectedValue = {
                                label: obj[props.label],
                                value: target
                            };
                        }
                    }
                } else {
                    state.selectedValue = {
                        label: target[props.valueLabelField],
                        value: target[props.keyField]
                    };
                }
            } else {
                state.selectedValue = {
                    label: '',
                    value: ''
                };
            }
            return attrs;
        });
        const slotNames = computed(() => {
            return Object.keys(slots);
        });
        const getOptions = async (name = '') => {
            showOptions.value = true;
            let requestApi: any = null;
            let query: any = {};
            switch (props.type) {
                case 'version':
                    requestApi = api.versionModel.findByName;
                    break;
                case 'versionNumber':
                    requestApi = api.versionModel.findByVersionNumber;
                    break;
                case 'taskRequire':
                    requestApi = api.pmpRequestInfoModel.findByRequireName;
                    break;
                case 'proRequire':
                    requestApi = api.productRequireModel.findByRequireName;
                    break;
                // 获取可以补录的产品需求列表
                case 'replenishPro':
                    requestApi = api.productProcessModel.getReplenishRequire;
                    break;
                // 根据系统查所有负责人
                case 'zhuanbanSystemManager':
                case 'systemManager':
                    requestApi = api.systemManagerModel.findManagersBySystem;
                    break;
                // 查询所有系统
                case 'mySystem':
                    requestApi = api.systemManagerModel.findBySystemAndEmpId;
                    break;
                // 需求统计PMP
                case 'platformSystem':
                    requestApi = api.productDetailModel.findAll;
                    break;
                case 'allSystem':
                    requestApi = api.systemManagerModel.findByAllSystems;
                    break;
                case 'typeSystem':
                    requestApi = api.productDetailModel.findBySystemType;
                    break;
                // 查询所有用户
                case 'allUser':
                    requestApi = api.userModel.getEmployeeList;
                    break;
                // 根据指定角色查用户
                case 'role':
                    requestApi = api.userModel.findByRole;
                    break;
                // 根据名称查系统设置的标签
                case 'systemLabel':
                    requestApi = api.labelModel.findLabelByName;
                    break;
                case 'jira':
                    requestApi = api.jiraModel.getIssuesBySummary;
                    break;
                case 'jiraVersion':
                    requestApi = api.jiraIssueModel.getFieldValueFromData;
                    break;
                case 'sprint':
                    requestApi = api.jiraIssueTrackModel.getFieldValueFromData;
                    break;
                case 'belong':
                    requestApi = api.productDetailModel.getProjectInfo;
                    break;
                case 'reportSystem':
                    requestApi = api.requireReportModel.findUnSetSystemsByName;
                    break;
                case 'versionSprint':
                    requestApi = api.jiraModel.getSprintByName;
                    break;
                case 'productLine':
                    requestApi = api.pbiProductCalendarModel.findPbiProductByName;
                    break;
                case 'workbenchVersion':
                    requestApi = api.versionModel.selectPage;
                    break;
                case 'fsFileName':
                    requestApi = api.fsFileSyncTmplModel.findFileSyncTmpls;
                    break;
                case 'getVersionsBySub':
                    requestApi = api.versionControlModel.getVersionsBySub;
                    break;
                case 'dataMergePro':
                    requestApi = api.dataMergeModel.findProductByName;
                    break;
                case 'findPreRat':
                    requestApi = api.dataMergeModel.findPreRat;
                    break;
                case 'findUpDownBySystemOrCatalogCode':
                    requestApi = api.productDetailModel.findUpDownBySystemOrCatalogCode;
                    break;
                default:
                    '';
            }
            switch (props.type) {
                case 'allUser':
                    query = {
                        pageSize: 100,
                        pageNum: 1,
                        condition: name
                    };
                    break;
                case 'systemManager':
                case 'zhuanbanSystemManager':
                    query = {
                        position: '产品经理',
                        ...props.searchQuery
                    };
                    break;
                case 'jira':
                    query = {
                        summary: name,
                        ...props.searchQuery
                    };
                    break;
                case 'workbenchVersion':
                    query = {
                        pageNum: 1,
                        pageSize: 0,
                        status: '1,2',
                        ...props.searchQuery,
                        versionNumber: name
                    };
                    break;
                case 'getVersionsBySub':
                    query = {
                        ...props.searchQuery,
                        versionNumber: name
                    };
                    break;
                default:
                    query = {
                        name,
                        ...props.searchQuery
                    };
            }
            const { success, moule, errorMsg, errorCode } = await requestApi(query, { cancelDuplicated: true });
            if (success) {
                switch (props.type) {
                    // 因为后续对接口进行改造所以需要兼容字段
                    case 'mySystem':
                    case 'allSystem':
                        if (moule && moule.length) {
                            options.value = moule.map((item) => ({
                                ...item,
                                system: item.systemName,
                                systemId: item.id
                            }));
                        }
                        break;
                    // 组织中心接口改动后，需要兼容旧数据
                    case 'allUser':
                        if (moule && moule.length) {
                            options.value = moule.map((item) => ({
                                ...item,
                                empId: item.userId,
                                empName: item.name
                            }));
                        }
                        break;
                    case 'fsFileName':
                        if (moule && moule.docs_entities.length) {
                            options.value = [...moule.docs_entities];
                        }
                        break;
                    default:
                        options.value = moule || [];
                }
                // 更新获取选项成功钩子
                emit('optionsCreated', unref(options));
            } else {
                emit('error', {
                    errorCode
                });
                message.error(errorMsg);
            }
            // 某些需要赋值默认值的进行特殊处理
            if (props.type === 'systemManager') {
                if (!attrs['default-value']) {
                    if (unref(options) && unref(options).length) {
                        let target = unref(options).find((item) => item.empId === store.getters.userInfo.employeeDTO.empId);
                        if (!target) {
                            target = unref(options)[0];
                        }
                        emit('success', target);
                    }
                }
            }
            if (props.type === 'zhuanbanSystemManager') {
                options.value = moule.filter((item) => item.empId !== store.getters.userInfo.employeeDTO.empId);
                if (!attrs['default-value']) {
                    let target = unref(options).find((item) => item.empId === store.getters.userInfo.employeeDTO.empId);
                    if (!target) {
                        target = unref(options)[0];
                    }
                    emit('success', target);
                }
            }
            if (props.type === 'productLine') {
                if (!attrs['default-value']) {
                    emit('success', unref(options)[0]);
                }
            }
            if (props.type === 'versionSprint') {
                if (attrs['default-value']) {
                    const target = unref(options).find((item) => item.name === attrs['default-value']);
                    if (target) {
                        emit('success', target);
                    }
                }
            }
        };
        // 搜索回调
        const selectSearch = (val) => {
            getDebounceOptions(val);
        };
        // 通用选择回调
        const selectChange = (val, arr) => {
            // 选择回调
            let target: any = null;
            if (val) {
                target = unref(options).find((item) => {
                    if (props.keyField) {
                        return item[props.keyField] === val.value;
                    } else {
                        return props.label ? item[props.label] === val.value : item === val.value;
                    }
                });
            }
            if (target) {
                emit('success', target); // 对应事件
                emit('update:value', target); // 对应v-model
            } else {
                emit('success', null); // 对应事件
                emit('update:value', null); // 对应v-model
                // getDebounceOptions();
            }
        };
        const buildOptionAttrs = (item) => {
            return {
                disabled: item?.xmzt ? ['9', '10'].includes(item.xmzt) : false
            };
        };
        // 输入
        /** @name 键盘按下时回调 **/
        const inputKeyDown = ({ code, target }) => {
            // 按下回车键
            if (code === 'Enter' && props.isAllowInput) {
                const inputValue = target.value;
                state.selectedValue = {
                    label: inputValue,
                    value: inputValue
                };
                emit('success', inputValue); // 对应事件
                emit('update:value', inputValue); // 对应v-model
            }
        };
        watch(
            () => props.searchQuery,
            (n, o) => {
                // 针对一些必须传的参数，最开始没传导致接口报错的，这种可以判断下么有必传的就不调用接口
                if (props.type === 'getVersionsBySub') {
                    if (!n.id) {
                        return;
                    }
                }
                // 如果最开始是禁用，则无需调用查询接口
                if (!attrs.disabled && JSON.stringify(n) !== JSON.stringify(o)) {
                    getOptions();
                }
            },
            {
                deep: true,
                immediate: true
            }
        );
        const getDebounceOptions = debounce(getOptions, 500);
        return {
            slotNames,
            ...toRefs(state),
            options,
            showOptions,
            bindValues,
            selectSearch,
            selectChange,
            getOptions,
            buildOptionAttrs,
            inputKeyDown
        };
    }
});
</script>
